package com.db.jdbc;

import com.common.utils.TableTypeUtils;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * 实体类ResultSet结果处理
 *
 * @author xin.ding
 * @date 2019/12/24 17:44
 */
public class BeanHandler<T> implements ResultSetHandler<List<T>> {

    /**
     * 创建字节码对象。传入需要操作的具体的类型字节码。就知道所操作的对象的具体类型。
     */
    private Class<T> clazz;

    /**
     * 创建有参构造函数，用于传入具体操作对象的类型
     */
    public BeanHandler(Class<T> clazz) {
        this.clazz = clazz;
    }

    /**
     * 数据库集操作类
     *
     * @param rs 数据库处理结果集
     * @return 数据库结果集 List 集合
     */
    @Override
    public List<T> handler(ResultSet rs) {
        // 创建 List 用于存放装箱后的对象
        List<T> list = new ArrayList<>(16);
        try {
            // 获取类的属性描述符
            BeanInfo beanInfo = Introspector.getBeanInfo(clazz, Object.class);
            PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
            // 对结果集进行装箱操作
            while (rs.next()) {
                T obj = clazz.newInstance();
                for (PropertyDescriptor descriptor : descriptors) {
                    //根据bean的属性名取oracle对应的字段值（要求属性与字段名必须一致）
                    Object value = rs.getObject(descriptor.getName());
                    //BigDecimal 类型处理
                    if (value instanceof BigDecimal) {
                        String type = descriptor.getPropertyType().getName();
                        value = convertBigDecimal((BigDecimal) value, type);
                    }
                    //调用具体的set方法
                    descriptor.getWriteMethod().invoke(obj, value);
                }
                list.add(obj);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    public static <T> T get(Class<T> clazz, Object o) {
        if (clazz.isInstance(o)) {
            return clazz.cast(o);
        }
        return null;

    }

    /**
     * 处理BigDecimal类型 转换为具体类型
     *
     * @param value BigDecimal
     * @param type  类型
     * @return value
     */
    private static Object convertBigDecimal(BigDecimal value, String type) {
        switch (type) {
            case TableTypeUtils.INT:
                return value.intValue();
            case TableTypeUtils.LONG:
                return value.longValue();
            case TableTypeUtils.FLOAT:
                return value.floatValue();
            case TableTypeUtils.DOUBLE:
                return value.doubleValue();
            default:
                return null;
        }
    }
}
